﻿using System;

namespace Cpu6502.Opcodes
{
    class EOR_I : Opcode
    {
        public EOR_I()
        {
            this.CpuCycles = 2;
            this.AddressType = CPU.AddressType.Immediate;
        }

        public override void Execute()
        {
            Byte temp = (byte)base.Argument;

            temp ^= CPU.Registers.A;

            // Set the Zero Flag if the data is 0
            CPU.Registers.P.Z = (temp == 0);

            // If bit 7 of register is set, then Negative flag must be set.
            CPU.Registers.P.N = (((temp << 7) & 1) != 0);

            CPU.Registers.A = temp;
        }
    }

    class EOR_ZP : Opcode
    {
        public EOR_ZP()
        {
            this.CpuCycles = 2;
            this.AddressType = CPU.AddressType.ZeroPage;
        }

        public override void Execute()
        {
            Byte temp =
                CPU.Memory
                [
                    MemoryHelper.GetAddress(base.Argument, CPU.AddressType.ZeroPage)
                ];

            temp ^= CPU.Registers.A;

            // Set the Zero Flag if the data is 0
            CPU.Registers.P.Z = (temp == 0);

            // If bit 7 of register is set, then Negative flag must be set.
            CPU.Registers.P.N = (((temp << 7) & 1) != 0);

            CPU.Registers.A = temp;
        }
    }

    class EOR_ZP_X : Opcode
    {
        public EOR_ZP_X()
        {
            this.CpuCycles = 3;
            this.AddressType = CPU.AddressType.ZeroPageIndexedX;
        }

        public override void Execute()
        {
            Byte temp =
                CPU.Memory
                [
                    MemoryHelper.GetAddress(base.Argument, CPU.AddressType.ZeroPageIndexedX)
                ];

            temp ^= CPU.Registers.A;

            // Set the Zero Flag if the data is 0
            CPU.Registers.P.Z = (temp == 0);

            // If bit 7 of register is set, then Negative flag must be set.
            CPU.Registers.P.N = (((temp << 7) & 1) != 0);

            CPU.Registers.A = temp;
        }
    }

    class EOR_A : Opcode
    {
        public EOR_A()
        {
            this.CpuCycles = 4;
            this.AddressType = CPU.AddressType.Absolute;
        }

        public override void Execute()
        {
            Byte temp =
                CPU.Memory
                [
                    MemoryHelper.GetAddress(base.Argument, CPU.AddressType.Absolute)
                ];

            temp ^= CPU.Registers.A;

            // Set the Zero Flag if the data is 0
            CPU.Registers.P.Z = (temp == 0);

            // If bit 7 of register is set, then Negative flag must be set.
            CPU.Registers.P.N = (((temp << 7) & 1) != 0);

            CPU.Registers.A = temp;
        }
    }

    class EOR_A_X : Opcode
    {
        public EOR_A_X()
        {
            this.CpuCycles = 4;
            this.AddressType = CPU.AddressType.AbsoluteIndexedX;
        }

        public override void Execute()
        {
            Byte temp =
                CPU.Memory
                [
                    MemoryHelper.GetAddress(base.Argument, CPU.AddressType.AbsoluteIndexedX)
                ];

            temp ^= CPU.Registers.A;

            // Set the Zero Flag if the data is 0
            CPU.Registers.P.Z = (temp == 0);

            // If bit 7 of register is set, then Negative flag must be set.
            CPU.Registers.P.N = (((temp << 7) & 1) != 0);

            CPU.Registers.A = temp;
        }
    }

    class EOR_A_Y : Opcode
    {
        public EOR_A_Y()
        {
            this.CpuCycles = 4;
            this.AddressType = CPU.AddressType.AbsoluteIndexedY;
        }

        public override void Execute()
        {
            Byte temp =
                CPU.Memory
                [
                    MemoryHelper.GetAddress(base.Argument, CPU.AddressType.AbsoluteIndexedY)
                ];

            temp ^= CPU.Registers.A;

            // Set the Zero Flag if the data is 0
            CPU.Registers.P.Z = (temp == 0);

            // If bit 7 of register is set, then Negative flag must be set.
            CPU.Registers.P.N = (((temp << 7) & 1) != 0);

            CPU.Registers.A = temp;
        }
    }

    class EOR_Index_Indirect : Opcode
    {
        public EOR_Index_Indirect()
        {
            this.CpuCycles = 6;
            this.AddressType = CPU.AddressType.IndexedIndirect;
        }

        public override void Execute()
        {
            Byte temp =
                CPU.Memory
                [
                    MemoryHelper.GetAddress(base.Argument, CPU.AddressType.IndexedIndirect)
                ];

            temp ^= CPU.Registers.A;

            // Set the Zero Flag if the data is 0
            CPU.Registers.P.Z = (temp == 0);

            // If bit 7 of register is set, then Negative flag must be set.
            CPU.Registers.P.N = (((temp << 7) & 1) != 0);

            CPU.Registers.A = temp;
        }
    }

    class EOR_Indirect_Index : Opcode
    {
        public EOR_Indirect_Index()
        {
            this.CpuCycles = 5;
            this.AddressType = CPU.AddressType.IndirectIndexed;
        }

        public override void Execute()
        {
            Byte temp =
                CPU.Memory
                [
                    MemoryHelper.GetAddress(base.Argument, CPU.AddressType.IndirectIndexed)
                ];

            temp ^= CPU.Registers.A;

            // Set the Zero Flag if the data is 0
            CPU.Registers.P.Z = (temp == 0);

            // If bit 7 of register is set, then Negative flag must be set.
            CPU.Registers.P.N = (((temp << 7) & 1) != 0);

            CPU.Registers.A = temp;
        }
    }
}